#include <tsin/SimpleMain.hpp>
#include <tsin/SimpleArgument.hpp>
#include <tsin/util/MemCheck.hpp>
#include <tsin/util/Logger.hpp>

#ifdef WIN32
#include <windows.h>
#endif

using namespace tsin;

int main(int argc, char *argv[])
{
        MEM_ON();

        SimpleMain main;
        SimpleArgument arg(argc, argv);
        int ret = main.main(arg);

        MEM_OFF();

        return ret;
}

#ifdef WIN32

/*
 * The 'isspace' in Windows requires the MSB of the character to be cleared.
 * Thus for command lines with ANSI characters, the assertion in it will fail.
 *
 * As on Windows ANSI encoding is used, there should not exist any Chinese
 * characters which contains a '0x20' byte and the judgement here should be safe.
 */
static bool _isspace(char c)
{
        return (c ==  ' ' || c == '\t' || c == '\n' ||
                c == '\r' || c == '\v' || c == '\f');
}

/*
 * This function is copied from src/main/win32/SDL_win32_main.c
 * in SDL source tarball without changes.
 */
static void UnEscapeQuotes( char *arg )
{
        char *last = NULL;

        while( *arg ) {
                if( *arg == '"' && *last == '\\' ) {
                        char *c_curr = arg;
                        char *c_last = last;

                        while( *c_curr ) {
                                *c_last = *c_curr;
                                c_last = c_curr;
                                c_curr++;
                        }
                        *c_last = '\0';
                }
                last = arg;
                arg++;
        }
}

/*
 * This function is copied from src/main/win32/SDL_win32_main.c
 * in SDL source tarball. The only change is replacing 'isspace' to '_isspace'.
 */
/* Parse a command line buffer into arguments */
static int ParseCommandLine(char *cmdline, char **argv)
{
        char *bufp;
        char *lastp = NULL;
        int argc, last_argc;

        argc = last_argc = 0;
        for ( bufp = cmdline; *bufp; ) {
                /* Skip leading whitespace */
                while ( _isspace(*bufp) ) {
                        ++bufp;
                }
                /* Skip over argument */
                if ( *bufp == '"' ) {
                        ++bufp;
                        if ( *bufp ) {
                                if ( argv ) {
                                        argv[argc] = bufp;
                                }
                                ++argc;
                        }
                        /* Skip over word */
                        while ( *bufp && ( *bufp != '"' || (lastp && *lastp == '\\') ) ) {
                                lastp = bufp;
                                ++bufp;
                        }
                } else {
                        if ( *bufp ) {
                                if ( argv ) {
                                        argv[argc] = bufp;
                                }
                                ++argc;
                        }
                        /* Skip over word */
                        while ( *bufp && ! _isspace(*bufp) ) {
                                ++bufp;
                        }
                }
                if ( *bufp ) {
                        if ( argv ) {
                                *bufp = '\0';
                        }
                        ++bufp;
                }

                /* Strip out \ from \" sequences */
                if( argv && last_argc != argc ) {
                        UnEscapeQuotes( argv[last_argc] );
                }
                last_argc = argc;
        }
        if ( argv ) {
                argv[argc] = NULL;
        }
        return(argc);
}

/*
 * This function is a copy of the code in SDLmain for command line parsing.
 */
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
        int argc;
        char **argv;
        char *cmdline, *bufp;
        size_t nLen;

        bufp = GetCommandLine();
        nLen = strlen(bufp) + 1;
        cmdline = new char[nLen];
        strcpy(cmdline, bufp);

        argc = ParseCommandLine(cmdline, 0);
        argv = new char*[argc + 1];
        ParseCommandLine(cmdline, argv);

        int ret = main(argc, argv);

        delete argv;
        delete cmdline;

        return 0;
}

#endif
